package view.panels;

import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import util.resources.ResourceManager;
import view.Pen;
import model.Turtle;
import controller.TurtleController;

/**
 * A frame for setting the preferences of a specific turtle.
 * 
 * @author Robert C Duvall
 * @author Anne Weng, Nathan Klug
 */
public class PreferencesFrame extends JFrame implements ActionListener
{
    private ResourceManager resourceManager = ResourceManager.getInstance();

    // used for serialization
    private static final long serialVersionUID = 1L;
    private Turtle myTurtle;
    private Checkbox penCheckBox, visibilityCheckBox;
    private JComboBox imageDropDownList, colorDropDownList;
    private JTextField lineWidthField;
    private TurtleController myController;

    private static final String TITLE = "Turtle ";
    private static final String IMAGE_LABEL = "Turtle image:";
    private static final String IMAGE_SOURCE = "turtleimages";
    private static final String COLOR_LABEL = "Pen color:";
    private static final String COLOR_SOURCE = "pencolors";
    private static final String LINEWIDTH_LABEL = "Line width:";
    private static final String PEN_DOWN_LABEL = "Pen down?";
    private static final String VISIBILITY_LABEL = "Turtle visible?";
    private static final String APPLY_LABEL = "Apply";

    /**
     * Create preferences frame with JComponents for setting turtle properties.
     */
    public PreferencesFrame(TurtleController controller, Turtle editingTurtle,
            int turtleID)
    {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setTitle(TITLE + turtleID);
        myController = controller;
        myTurtle = editingTurtle;

        addComponents();
    }

    /**
     * Populates the frame with JComponents
     * 
     * @param currentPenState
     * @param currentVisibility
     */
    private void addComponents()
    {
        // Creates labels for current location and heading
        int currentX = (int) myTurtle.getX();
        int currentY = (int) myTurtle.getY();
        int currentHeading = (int) myTurtle.getAngle().getDegrees();
        String locationString = "Location: (" + currentX + "," + currentY + ")";
        JLabel turtleLocation = createLabel(locationString);
        String headingString = "Heading: " + currentHeading + " degrees";
        JLabel turtleHeading = createLabel(headingString);

        // Gets the list of possible turtles and creates a JComboBox
        JLabel turtleImageLabel = createLabel(IMAGE_LABEL);
        imageDropDownList = createDropDownList(IMAGE_SOURCE);

        // Gets the list of possible colors and creates a JComboBox
        JLabel penColorLabel = createLabel(COLOR_LABEL);
        colorDropDownList = createDropDownList(COLOR_SOURCE);

        // Allows the user to input their own line width
        JLabel lineWidthLabel = createLabel(LINEWIDTH_LABEL);
        lineWidthField = new JTextField("1.0");
        lineWidthField.setFont(new Font("monospaced", Font.PLAIN, 12));
        lineWidthField.setHorizontalAlignment(JTextField.RIGHT);

        // Checkbox for setting pen down/up
        penCheckBox = new Checkbox(PEN_DOWN_LABEL, myTurtle.getPen()
                .isPenDown());

        // Checkbox for making turtle visible/invisible
        visibilityCheckBox = new Checkbox(VISIBILITY_LABEL,
                myTurtle.isVisible());

        // Make a save changes button
        AbstractButton applyButton = new JButton(APPLY_LABEL);
        applyButton.setMnemonic(KeyEvent.VK_S);
        applyButton.addActionListener(this);

        // Make these items appear.
        Container content = this.getContentPane();
        GridLayout gridLayout = new GridLayout(6, 2);
        content.setLayout(gridLayout);
        content.add(turtleLocation);
        content.add(turtleHeading);
        content.add(turtleImageLabel);
        content.add(imageDropDownList);
        content.add(penColorLabel);
        content.add(colorDropDownList);
        content.add(lineWidthLabel);
        content.add(lineWidthField);
        content.add(visibilityCheckBox);
        content.add(penCheckBox);
        content.add(new JLabel()); // Blank space so Apply is on the right
        content.add(applyButton);

        this.setContentPane(content);
        /*
         * Done.
         */
        pack();
    }

    /**
     * Creates a JLabel from a string
     * 
     * @return JLabel
     * @param labelText
     */
    private JLabel createLabel(String labelText)
    {
        JLabel penColorLabel = new JLabel();
        penColorLabel.setText(labelText);
        return penColorLabel;
    }

    /**
     * Creates a JComboBox from a resource file
     * 
     * @return JComboBox
     * @param source
     */
    private JComboBox createDropDownList(String source)
    {
        Object[] possibleList = resourceManager
                .getAndAddResourcesFromFile(source).keySet().toArray();
        return new JComboBox(possibleList);
    }

    /**
     * Apply changes when button is pressed.
     */
    @Override
    public void actionPerformed(ActionEvent e)
    {
        // Creates image from selected image
        String turtleName = (String) imageDropDownList.getSelectedItem();
        Image newImage = null;
        try
        {
            newImage = ImageIO.read(new File(resourceManager
                    .getString(turtleName)));
        }
        catch (IOException e1)
        {
            return; // Shouldn't happen hopefully with this resource setup
        }

        // Creates color from selected color
        String colorName = (String) colorDropDownList.getSelectedItem();
        Color newColor = resourceManager.getColor(colorName);

        // Tries to parse the number and gives message if error
        Float newlineWidth = (float) 1.0;
        try
        {
            newlineWidth = Float.parseFloat(lineWidthField.getText());
        }
        catch (NumberFormatException e2)
        {
            JOptionPane.showMessageDialog(this, "Line width is not a number.");
            return;
        }

        // Checks the states of the checkboxes
        boolean newPenState = penCheckBox.getState();
        boolean newVisibility = visibilityCheckBox.getState();

        // Creates new pen from all of the above
        Pen newPen = new Pen(newColor, newPenState, newlineWidth);

        // Updates the turtle
        actions.PropertyAction modifyTurtle = new actions.PropertyAction(
                myTurtle, newVisibility, newPen, newImage);
        myController.update(null, modifyTurtle);

        dispose(); // Close window when done
    }

}